/***************************************************************************
 *   Copyright (C) 2007 by Ivan Vasić              *
 *   ivasic@gmail.com                  *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "exception.h"

#include <QObject>
#include <QString>

Exception::Exception()
		: QObject(0l)
{
	m_type = Normal;
	m_innerException = 0l;
	m_lineNumber = 0;
	m_filename = m_message = m_methodName = QString::null;
}

Exception::~Exception()
{
	if (m_innerException)
		delete m_innerException;
}

Exception::Exception(const QString& msg, ExceptionType type)
		: QObject(0l), m_message(msg), m_type(type)
{
	m_innerException = 0l;
	m_lineNumber = 0;
	m_filename = m_methodName = QString::null;
}

Exception::Exception(const QString & msg, ExceptionType type, const QString & filename, const QString & methodName, int lineNr, Exception* innerException)
		: QObject(0l), m_message(msg), m_type(type), m_filename(filename), m_methodName(methodName), m_lineNumber(lineNr), m_innerException(innerException)
{}

Exception::Exception(const Exception & ex)
		: QObject(0l)
{
	m_message = ex.m_message;
	m_type = ex.m_type;
	m_methodName = ex.m_methodName;
	m_filename = ex.m_filename;
	m_lineNumber = ex.m_lineNumber;
	m_innerException = ex.m_innerException;
}

Exception & Exception::operator =(const Exception & ex)
{
	m_message = ex.m_message;
	m_type = ex.m_type;
	m_methodName = ex.m_methodName;
	m_filename = ex.m_filename;
	m_lineNumber = ex.m_lineNumber;
	m_innerException = ex.m_innerException;

	return *this;
}

const QString Exception::debug() const
{	
	QString args;

	QMapIterator<QString, QString> it(m_arguments);

	while (it.hasNext())
	{
		it.next();
		args.append(it.key() + "=" + it.value() + ", ");
	}

	return tr("%1:%2: %6 exception in: %3(%4) with message: \"%5\" \r\n").arg(m_filename).arg(m_lineNumber).arg(m_methodName).arg(args).arg(m_message).arg(typeToString(m_type));
}

QString Exception::typeToString(ExceptionType type) const
{
	switch(type)
	{
		case(Normal):
			return tr("Normal");
		case(Critical):
			return tr("Critical");
		case(Fatal):
			return tr("Fatal");
		default:
			return tr("Unknown");
	}
}

QString Exception::getBacktrace() const
{
	///@TODO: Obrni trace. Treba se poziva rekurzivno.
	
	const Exception* ex = this;
	
	QString msg = QString("#0 0x%1 %2").arg((quint32)this,0,16).arg(ex->debug());
	
	int i = 0;
	while(ex->m_innerException != 0)
	{
		++i;
		ex = ex->m_innerException;
		msg += QString("#%1 0x%2 %3").arg(i).arg((quint32)ex,0,16).arg(ex->debug());				
	}
	
	return msg;
}
